﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net;
using System.Collections.Generic;

namespace UnitTestGetNavi
{
    [TestClass]
    public class UnitTestGetNavi
    {
        private int statuscode;
        private string statustext = "";
        private string data = "";
        private Dictionary<string, HashSet<string>> streetCityDict;

        [TestMethod]
        [ExpectedException(typeof(FileNotFoundException))]
        public void Update_WithNonExistingFile_ShouldThrowFileNotFoundException()
        {
            streetCityDict = new Dictionary<string, HashSet<string>>();
            Plugin.MapReader mp = new Plugin.MapReader("GetNavi", "DontExist.osm", streetCityDict);
            mp.Update("DontExist.osm");
        }

        [TestMethod]
        public void Update_WithExistingFile_ShouldHaveValidDictionary()
        {
            streetCityDict = new Dictionary<string, HashSet<string>>();
            Plugin.MapReader mp = new Plugin.MapReader("GetNavi", "Plugins\\GetNavi\\map.osm", streetCityDict);
            mp.Update("Plugins\\GetNavi\\map.osm");
            streetCityDict = mp.streetCityDict;
            Assert.IsTrue(streetCityDict.ContainsKey("Kärntnerstraße"));
            Assert.IsTrue(streetCityDict["Kärntnerstraße"].Contains("Wien"));
            Assert.IsTrue(streetCityDict.ContainsKey("Hardlgasse"));
            Assert.IsTrue(streetCityDict.ContainsKey("Marktgasse"));
            Assert.IsTrue(streetCityDict.ContainsKey("Neunkirchner Straße"));
            Assert.IsTrue(streetCityDict["Hardlgasse"].Contains("Wiener Neustadt"));
            Assert.IsTrue(streetCityDict["Marktgasse"].Contains("Wiener Neustadt"));
            Assert.IsTrue(streetCityDict["Neunkirchner Straße"].Contains("Wiener Neustadt"));
        }

        [TestMethod]
        public void ExecutePlugin_TestLoadingMap_ShouldReturnValidResponse()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55124);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55124);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("GET /GetNavi?action=refreshMap HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Connection: close");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(200, statuscode);
            Assert.AreEqual("OK", statustext, true);
            bool b = data.Contains("Die Karte wird nun neu eingelesen...");
            Assert.IsTrue(b);
        }
        [TestMethod]
        public void ExecutePlugin_SearchForExistingStreet_ShouldReturnValidResponse()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55124);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55124);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("POST /GetNavi HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Content-Length: 47");
            writer.WriteLine();
            writer.WriteLine("searchInputField=Hardlgasse&submit=Stadt suchen");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(200, statuscode);
            Assert.AreEqual("OK", statustext, true);
            bool b = data.Contains("Wiener Neustadt");
            Assert.IsTrue(b);
        }
        [TestMethod]
        public void ExecutePlugin_SearchForNonExistingStreet_ShouldReturnValidResponse()
        {
            TcpListener server = new TcpListener(IPAddress.Any, 55124);

            ParameterizedThreadStart pts = new ParameterizedThreadStart(this.newThreadMethod);
            Thread thread = new Thread(pts);
            thread.Start(server);

            TcpClient client = new TcpClient("127.0.0.1", 55124);
            NetworkStream stream = client.GetStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.WriteLine("POST /GetNavi HTTP/1.1");
            writer.WriteLine("Host: localhost");
            writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
            writer.WriteLine("Content-Length: 47");
            writer.WriteLine();
            writer.WriteLine("searchInputField=ExistiertNichtgasse&submit=Stadt suchen");
            writer.Flush();
            client.Close();

            thread.Join(); //warten bis Response vom anderen Thread generiert wurde

            Assert.AreEqual(200, statuscode);
            Assert.AreEqual("OK", statustext, true);
            bool b = data.Contains("Es konnte keine Stadt gefunden werden, in der es diese Strasse gibt.");
            Assert.IsTrue(b);
        }
        private void newThreadMethod(Object parameter)
        {
            TcpListener server = (TcpListener)parameter;
            server.Start();
            Socket so = server.AcceptSocket();
            IPlugin.Request req = new IPlugin.Request(so);
            req.Parse();

            Plugin.Plugin getNaviPlugin = new Plugin.Plugin();
            HashSet<string> hset = new HashSet<string>();
            hset.Add("Wiener Neustadt");
            getNaviPlugin.streetCityDict.Add("Hardlgasse", hset);
            IPlugin.Response resp = getNaviPlugin.ExecutePlugin(req);
            statuscode = resp.StatusCode;
            statustext = resp.StatusText;
            data = resp.Data;

            server.Stop();
        }

    }
}
